﻿using Framework.Common;
using System.Collections.Generic;

namespace Framework.Resource
{
    /// <summary>
    /// 资源包
    /// </summary>
    public class AssetPackage
    {
        /// <summary>
        /// 引用该资源包的资源包集合
        /// </summary>
        private List<AssetPackage> m_ReferencePackages = null;
        /// <summary>
        /// 依赖的资源包集合
        /// </summary>
        private List<AssetPackage> m_DependentPackages = null;
        /// <summary>
        /// 资源列表
        /// </summary>
        private Dictionary<string, AssetInfo> m_Assets = null;
        /// <summary>
        /// 资源包名称
        /// </summary>
        private string m_PackageName = null;
        /// <summary>
        /// 加载资源帮助类
        /// </summary>
        private IAssetHelper m_LoadAssetHelper = null;
        /// <summary>
        /// 资源包
        /// </summary>
        private object m_PackageAsset = null;

        /// <summary>
        /// 资源包
        /// </summary>
        public object PackageAsset
        {
            get
            {
                return m_PackageAsset;
            }
        }
        /// <summary>
        /// 资源包名称
        /// </summary>
        public string PackageName
        {
            get
            {
                return m_PackageName;
            }
        }
        /// <summary>
        /// 获得所有已经加载了的资源
        /// </summary>
        public List<AssetInfo> HasLoadedAssets
        {
            get
            {
                List<AssetInfo> assets = new List<AssetInfo>();
                foreach (var item in m_Assets)
                {
                    assets.Add(item.Value);
                }
                return assets;
            }
        }
        /// <summary>
        /// 引用该资源包的资源包集合
        /// </summary>
        public List<AssetPackage> ReferencePackages
        {
            get
            {
                return m_ReferencePackages;
            }
        }
        /// <summary>
        /// 依赖的所有资源包
        /// </summary>
        public List<AssetPackage> DependentPackages
        {
            get
            {
                return m_DependentPackages;
            }
        }
        /// <summary>
        /// 资源包是可以释放
        /// </summary>
        public bool IsFree
        {
            get
            {
                if (m_ReferencePackages.Count > 0)
                    return false;
                foreach (var item in m_Assets)
                {
                    if (item.Value.IsFree == false)
                        return false;
                }
                return true;
            }
        }

        /// <summary>
        /// 创建资源包实例
        /// </summary>
        /// <param name="packageName">资源包名称</param>
        /// <param name="packageAsset">资源包</param>
        /// <param name="loadAssetHepler">资源加载帮助类</param>
        public AssetPackage(string packageName, object packageAsset, IAssetHelper loadAssetHepler)
        {
            m_PackageName = packageName;
            m_PackageAsset = packageAsset;
            m_Assets = new Dictionary<string, AssetInfo>();
            m_LoadAssetHelper = loadAssetHepler;
            m_DependentPackages = new List<AssetPackage>();
            m_ReferencePackages = new List<AssetPackage>();
        }
        /// <summary>
        /// 加载资源
        /// </summary>
        /// <param name="assetName">资源名称</param>
        public object LoadAsset(string assetName)
        {
            if (m_PackageAsset == null)
                return null;
            if (m_Assets.ContainsKey(assetName))
                return m_Assets[assetName].Asset;
            object obj = m_LoadAssetHelper.LoadAssetFromPackage(m_PackageAsset, assetName);
            if(obj == null)
            {
                throw new  FrameworkException("load asset failed!");
            }
            AssetInfo assetInfo = new AssetInfo(obj);
            m_Assets.Add(assetName, assetInfo);
            return obj;
        }
        /// <summary>
        /// 加载资源
        /// </summary>
        /// <typeparam name="T">资源类型</typeparam>
        /// <param name="assetName">资源名称</param>
        public T LoadAsset<T>(string assetName)
        {
            if (m_PackageAsset == null)
                return default(T);
            if (m_Assets.ContainsKey(assetName))
                return (T)m_Assets[assetName].Asset;
            T obj = m_LoadAssetHelper.LoadAssetFromPackage<T>(m_PackageAsset, assetName);
            if(obj == null)
            {
                throw new FrameworkException("load asset failed!");
            }
            AssetInfo assetInfo = new AssetInfo(obj);
            m_Assets.Add(assetName, assetInfo);
            return obj;
        }
        /// <summary>
        /// 增加资源引用计数
        /// </summary>
        /// <param name="assetName">资源名称</param>
        public void AddAssetReferenceCount(string assetName)
        {
            if (m_Assets.ContainsKey(assetName))
                m_Assets[assetName].AddAssetReference();
        }
        /// <summary>
        /// 减少资源引用计数
        /// </summary>
        /// <param name="assetName"></param>
        public void MinusAssetReferenceCount(string assetName)
        {
            if (m_Assets.ContainsKey(assetName))
                m_Assets[assetName].MinusAssetReference();
        }
        /// <summary>
        /// 添加资源引用
        /// </summary>
        /// <param name="assetName">资源名称</param>
        /// <param name="instance">要添加的资源实例</param>
        public void AddAssetInstance(string assetName, object instance)
        {
            if(m_Assets.ContainsKey(assetName))
                m_Assets[assetName].AddAssetInstance(instance);
        }
        /// <summary>
        /// 删除资源实例
        /// </summary>
        /// <param name="assetName">资源名称</param>
        /// <param name="instance">要删除的资源实例</param>
        public void RemoveAssetInstance(string assetName, object instance)
        {
            if(m_Assets.ContainsKey(assetName))
                m_Assets[assetName].RemoveAssetInstance(instance);
        }
        /// <summary>
        /// 添加依赖的资源包
        /// </summary>
        /// <param name="packageName">资源包名称</param>
        public void AddDependentPackage(AssetPackage package)
        {
            if (m_DependentPackages.Contains(package)) return;
            m_DependentPackages.Add(package);
        }
        /// <summary>
        /// 删除依赖的资源包
        /// </summary>
        /// <param name="packageName">资源包名称</param>
        public void RemoveDependentPacakge(AssetPackage package)
        {
            if (!m_DependentPackages.Contains(package)) return;
            m_DependentPackages.Remove(package);
        }
        /// <summary>
        /// 添加引用该资源包的资源包
        /// </summary>
        /// <param name="packageName">资源包名称</param>
        public void AddReferencePackage(AssetPackage package)
        {
            if (m_ReferencePackages.Contains(package)) return;
            m_ReferencePackages.Add(package);
        }
        /// <summary>
        /// 删除引用该资源包的资源包
        /// </summary>
        /// <param name="packageName">资源包名称</param>
        public void RemoveReferencePackage(AssetPackage package)
        {
            if (!m_ReferencePackages.Contains(package)) return;
            m_ReferencePackages.Remove(package);
        }
        /// <summary>
        /// 释放资源包
        /// </summary>
        public void ReleasePackage()
        {
            if (m_LoadAssetHelper != null && m_PackageAsset != null)
                m_LoadAssetHelper.ReleaseAssetPackage(m_PackageAsset);
            for (int i = 0; i < m_DependentPackages.Count; i++)
                m_DependentPackages[i].RemoveReferencePackage(this);
            for (int i = 0; i < m_ReferencePackages.Count; i++)
                m_ReferencePackages[i].RemoveDependentPacakge(this);
            m_ReferencePackages.Clear();
            m_DependentPackages.Clear();
            m_Assets.Clear();
        }
    }
}
